--- /dev/null
+// writes a message to the MSI logs
+function logInfo(message) {
+ var record = Session.Installer.CreateRecord(0);
+ record.stringData(0) = message
+ // 0x40000000 = msiMessageTypeUser -- see https://learn.microsoft.com/en-gb/windows/win32/msi/session-message#parameters
+ Session.Message(0x04000000, record)
+}
+
+function EnsureACL() {
+ var shell = new ActiveXObject("WScript.Shell");
+ var fs = new ActiveXObject("Scripting.FileSystemObject");
+
+ var programFilesPath = fs.GetAbsolutePathName(shell.ExpandEnvironmentStrings("%PROGRAMFILES%"));
+ var installPath = fs.GetAbsolutePathName(Session.Property("CustomActionData"));
+
+ logInfo("programFilesPath: " + programFilesPath + "\r\n" + "installPath: " + installPath);
+
+ if (installPath.toLowerCase().indexOf(programFilesPath.toLowerCase()) == 0) {
+ // no need to adapt ACLs when installing to C:/Program Files
+ return 0;
+ }
+
+ // using SIDs here (prefixed by *) to avoid potential issues with non-English installs
+ // see also: https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids
+ var grants = [
+ "*S-1-5-32-544:(OI)(CI)F", // DOMAIN_ALIAS_RID_ADMINS => full access
+ "*S-1-5-18:(OI)(CI)F", // SECURITY_LOCAL_SYSTEM_RID => full access
+ "*S-1-5-32-545:(OI)(CI)RX" // DOMAIN_ALIAS_RID_USERS => read, execute
+ ];
+ var grantsOptions = "";
+ for (var i = 0; i < grants.length; i++) {
+ grantsOptions += ' /grant "' + grants[i] + '" ';
+ }
+
+ var icaclsCommand = 'icacls.exe "' + installPath + '" /inheritance:r ' + grantsOptions;
+ logInfo("Command: " + icaclsCommand);
+ var retval = shell.Run(icaclsCommand, 0, true);
+ if (retval != 0) {
+ logInfo("Return code: " + retval);
+ return 1603; // fatal error
+ }
+
+ return 0;
+}
<!-- Detect legacy NSIS installation -->
<Property Id="NSIS_UNINSTALLEXE">
<RegistrySearch Id="RegistryLegacyUninstallString" Type="file" Root="HKLM" Key="Software\Microsoft\Windows\CurrentVersion\Uninstall\$(var.AppName)" Name="UninstallString" Win64="no">
- <FileSearch Id="LegacyUninstallFileName" Name="Uninstall.exe"/>
- </RegistrySearch>
+ <FileSearch Id="LegacyUninstallFileName" Name="Uninstall.exe"/>
+ </RegistrySearch>
</Property>
<!-- Property to disable update checks -->
<SetProperty Id="ExecNsisUninstaller" Value=""$(var.AppShortName)" "[NSIS_UNINSTALLEXE]"" Before="ExecNsisUninstaller" Sequence="execute" />
<SetProperty Id="RemoveNavigationPaneEntries" Value=""$(var.AppName)"" Before="RemoveNavigationPaneEntries" Sequence="execute" />
+ <!-- Ensure ACLs -->
+ <Binary Id="EnsureACL" SourceFile="EnsureACL.js" />
+ <SetProperty Id="EnsureACL" Before="EnsureACL" Value="[INSTALLDIR]" Sequence="execute" />
+ <CustomAction Id="EnsureACL" BinaryKey="EnsureACL" JScriptCall="EnsureACL" Return="check" Execute="deferred" Impersonate="no" />
+
<InstallExecuteSequence>
<!-- Install: Remove previous NSIS installation, if detected -->
<Custom Action="ExecNsisUninstaller" Before="ProcessComponents">NSIS_UNINSTALLEXE AND NOT Installed</Custom>
+ <!-- Install: Ensure ACLs are set -->
+ <Custom Action="EnsureACL" After="InstallFiles">NOT Installed</Custom>
+
<!-- Uninstall: Remove sync folders from Explorer's Navigation Pane, only effective for the current user (home users) -->
<Custom Action="RemoveNavigationPaneEntries" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
-
- <!-- Uninstall: Cleanup the Registry -->
- <Custom Action="RegistryCleanupCustomAction" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
+
+ <!-- Uninstall: Cleanup the Registry -->
+ <Custom Action="RegistryCleanupCustomAction" After="RemoveFiles">(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")</Custom>
<!-- Schedule Reboot for the Shell Extensions (in silent installation mode only, or if SCHEDULE_REBOOT argument is set-->
<ScheduleReboot After="InstallFinalize">(SCHEDULE_REBOOT=1) OR NOT (UILevel=2)</ScheduleReboot>
</InstallExecuteSequence>
<!-- "Add or Remove" Programs Entries -->
- <Property Id="APPNAME">$(var.AppName)</Property>
+ <Property Id="APPNAME">$(var.AppName)</Property>
<Property Id="ARPPRODUCTICON">$(var.AppIcon)</Property>
<Property Id="ARPHELPLINK">$(var.AppHelpLink)</Property>
<Property Id="ARPURLINFOABOUT">$(var.AppInfoLink)</Property>
<RegistryValue Type="integer" Name="skipUpdateCheck" Value="[SKIPAUTOUPDATE]" />
</RegistryKey>
</Component>
- <!-- Register URI handler -->
+ <!-- Register URI handler -->
<Component Id="RegistryUriHandler" Guid="*" Win64="$(var.PlatformWin64)">
<RegistryKey Root="HKLM" Key="Software\Classes\$(var.AppCommandOpenUrlScheme)" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Type="string" Value="URL:$(var.AppName) Protocol" />
- <RegistryValue Type="string" Name="URL Protocol" Value="" />
+ <RegistryValue Type="string" Name="URL Protocol" Value="" />
</RegistryKey>
<RegistryKey Root="HKLM" Key="Software\Classes\$(var.AppCommandOpenUrlScheme)\DefaultIcon" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Type="string" Value="[INSTALLDIR]$(var.AppExe)" />
<ComponentRef Id="RegistryVersionInfo" />
<ComponentRef Id="RegistryDefaultSettings" />
- <ComponentRef Id="RegistryUriHandler" />
+ <ComponentRef Id="RegistryUriHandler" />
<Feature Id="ShellExtensions" Title="Integration for Windows Explorer"
Description="This feature requires a reboot." >